﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using ERP.ERPModels.HumanResources.MasterData;
using ERP.HumanResources.HumanResourceManagement.Dtos;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace ERP.HumanResources.HumanResourceManagement
{
    public class PositionLevelService : ApplicationService, IPositionLevelService
    {
        private readonly IRepository<PositionLevel, int> _positionLevelRepository;

        public PositionLevelService(IRepository<PositionLevel, int> positionLevelRepository)
        {
            _positionLevelRepository = positionLevelRepository;
        }

        /// <summary>
        /// 获取职级列表
        /// </summary>
        public async Task<PagedResultDto<PositionLevelDto>> GetListAsync(GetPositionLevelInputDto input)
        {
            var query = await CreateFilteredQueryAsync(input);

            var totalCount = query.Count();

            query = ApplySorting(query, input);

            query = query.PageBy(input.SkipCount, input.MaxResultCount);

            var items =  query.ToList();

            return new PagedResultDto<PositionLevelDto>(
                totalCount,
                ObjectMapper.Map<List<PositionLevel>, List<PositionLevelDto>>(items)
            );
        }

        /// <summary>
        /// 获取职级详情
        /// </summary>
        public async Task<PositionLevelDto> GetAsync(int id)
        {
            var positionLevel = await _positionLevelRepository.GetAsync(id);
            return ObjectMapper.Map<PositionLevel, PositionLevelDto>(positionLevel);
        }

        /// <summary>
        /// 创建职级
        /// </summary>
        public async Task<PositionLevelDto> CreateAsync(CreatePositionLevelDto input)
        {
            // 检查职级编码是否已存在
            var existingPositionLevel = await _positionLevelRepository.FirstOrDefaultAsync(x => x.JobGradeCoding == input.JobGradeCoding);
            if (existingPositionLevel != null)
            {
                throw new UserFriendlyException("职级编码已存在");
            }

            // 检查薪资范围合法性
            if (input.SalaryRangelower > input.SalaryRangelimits)
            {
                throw new UserFriendlyException("薪资范围下限不能大于上限");
            }

            var positionLevel = ObjectMapper.Map<CreatePositionLevelDto, PositionLevel>(input);
            
            await _positionLevelRepository.InsertAsync(positionLevel);

            await CurrentUnitOfWork.SaveChangesAsync();

            return ObjectMapper.Map<PositionLevel, PositionLevelDto>(positionLevel);
        }

        /// <summary>
        /// 更新职级
        /// </summary>
        public async Task<PositionLevelDto> UpdateAsync(int id, UpdatePositionLevelDto input)
        {
            // 确保id与input.Id一致
            if (id != input.Id && input.Id != 0)
            {
                id = input.Id;
            }
            
            var positionLevel = await _positionLevelRepository.GetAsync(id);

            // 检查职级编码是否已存在（排除自身）
            var existingPositionLevel = await _positionLevelRepository.FirstOrDefaultAsync(x => x.JobGradeCoding == input.JobGradeCoding && x.Id != id);
            if (existingPositionLevel != null)
            {
                throw new UserFriendlyException("职级编码已存在");
            }

            // 检查薪资范围合法性
            if (input.SalaryRangelower > input.SalaryRangelimits)
            {
                throw new UserFriendlyException("薪资范围下限不能大于上限");
            }

            ObjectMapper.Map(input, positionLevel);
            
            await _positionLevelRepository.UpdateAsync(positionLevel);

            await CurrentUnitOfWork.SaveChangesAsync();

            return ObjectMapper.Map<PositionLevel, PositionLevelDto>(positionLevel);
        }

        /// <summary>
        /// 删除职级
        /// </summary>
        public async Task DeleteAsync(int id)
        {
            await _positionLevelRepository.DeleteAsync(id);
            await CurrentUnitOfWork.SaveChangesAsync();
        }

        /// <summary>
        /// 批量删除职级
        /// </summary>
        public async Task BatchDeleteAsync(List<int> ids)
        {
            foreach (var id in ids)
            {
                await _positionLevelRepository.DeleteAsync(id);
            }

            await CurrentUnitOfWork.SaveChangesAsync();
        }

        /// <summary>
        /// 导出职级
        /// </summary>
        public async Task<byte[]> ExportAsync(GetPositionLevelInputDto input)
        {
            var query = await CreateFilteredQueryAsync(input);
            query = ApplySorting(query, input);
            var items =  query.ToList();

            using var ms = new MemoryStream();
            IWorkbook workbook = new XSSFWorkbook();
            ISheet sheet = workbook.CreateSheet("职级管理");

            // 创建表头
            var headerRow = sheet.CreateRow(0);
            headerRow.CreateCell(0).SetCellValue("职级编码");
            headerRow.CreateCell(1).SetCellValue("职级层次");
            headerRow.CreateCell(2).SetCellValue("职级层次名称");
            headerRow.CreateCell(3).SetCellValue("薪资范围下限");
            headerRow.CreateCell(4).SetCellValue("薪资范围上限");
            headerRow.CreateCell(5).SetCellValue("备注");

            // 填充数据
            for (int i = 0; i < items.Count; i++)
            {
                var item = items[i];
                var row = sheet.CreateRow(i + 1);
                row.CreateCell(0).SetCellValue(item.JobGradeCoding);
                row.CreateCell(1).SetCellValue(item.JobGradeLevel);
                row.CreateCell(2).SetCellValue(item.JobGradeLevelName);
                row.CreateCell(3).SetCellValue(item.SalaryRangelower);
                row.CreateCell(4).SetCellValue(item.SalaryRangelimits);
                row.CreateCell(5).SetCellValue(item.ReferenceColumn ?? "");
            }

            // 自适应列宽
            for (int i = 0; i < 6; i++)
            {
                sheet.AutoSizeColumn(i);
            }

            workbook.Write(ms);
            return ms.ToArray();
        }

        /// <summary>
        /// 创建过滤查询
        /// </summary>
        private async Task<IQueryable<PositionLevel>> CreateFilteredQueryAsync(GetPositionLevelInputDto input)
        {
            var query = await _positionLevelRepository.GetQueryableAsync();

            // 关键字搜索
            if (!string.IsNullOrWhiteSpace(input.Keyword))
            {
                query = query.Where(x =>
                    x.JobGradeCoding.Contains(input.Keyword) ||
                    x.JobGradeLevel.Contains(input.Keyword) ||
                    x.JobGradeLevelName.Contains(input.Keyword));
            }

            // 职级编码
            if (!string.IsNullOrWhiteSpace(input.JobGradeCoding))
            {
                query = query.Where(x => x.JobGradeCoding.Contains(input.JobGradeCoding));
            }

            // 职级层次
            if (!string.IsNullOrWhiteSpace(input.JobGradeLevel))
            {
                query = query.Where(x => x.JobGradeLevel.Contains(input.JobGradeLevel));
            }

            // 薪资范围下限
            if (input.MinSalaryRangelower.HasValue)
            {
                query = query.Where(x => x.SalaryRangelower >= input.MinSalaryRangelower.Value);
            }

            if (input.MaxSalaryRangelower.HasValue)
            {
                query = query.Where(x => x.SalaryRangelower <= input.MaxSalaryRangelower.Value);
            }

            // 薪资范围上限
            if (input.MinSalaryRangelimits.HasValue)
            {
                query = query.Where(x => x.SalaryRangelimits >= input.MinSalaryRangelimits.Value);
            }

            if (input.MaxSalaryRangelimits.HasValue)
            {
                query = query.Where(x => x.SalaryRangelimits <= input.MaxSalaryRangelimits.Value);
            }

            return query;
        }

        /// <summary>
        /// 应用排序
        /// </summary>
        private IQueryable<PositionLevel> ApplySorting(IQueryable<PositionLevel> query, GetPositionLevelInputDto input)
        {
            // 如果没有指定排序，默认按照职级层次排序
            if (string.IsNullOrWhiteSpace(input.Sorting))
            {
                return query.OrderBy(x => x.JobGradeLevel);
            }

            return query.OrderBy(input.Sorting);
        }
    }
}
